abstract class Component {
    abstract operate() : void;
}

class ConcreteComponent extends Component {
    operate() {
        console.log('do something');
    }
}

abstract class Decorator extends Component {
    component: Component;
    protected constructor(component: Component) {
        super();
        this.component = component;
    }
    operate() {
        this.component.operate();
    }
}

class ConcreteDecorator1 extends Decorator {
    constructor(component: Component) {
        super(component);
    }
    operate() {
        this.extraOperate();
        super.operate();
    }
    private extraOperate() {
        console.log('decorator1 extra operate');
    }
}

class ConcreteDecorator2 extends Decorator {
    constructor(component: Component) {
        super(component);
    }
    operate() {
        this.extraOperate();
        super.operate();
    }
    private extraOperate() {
        console.log('decorator2 extra operate');
    }
}

const comp = new ConcreteDecorator1(new ConcreteDecorator2(new ConcreteComponent()));
comp.operate();